﻿namespace Library
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Collections;
    using Library.Definition;
    using System.Diagnostics;

    public class BallRelationalDependenceCheck
    {
        public void PrintInstances(string fileName)
        {
            var fileLines = File.ReadAllLines(fileName);
            var numLines = fileLines.Length;
            IList<int> relatedLineNumbers = new List<int>();
            int lineAdded = -1; 

            for (int i = 1; i < numLines - 1; i++)
            {
                string []words;
                if (fileLines[i].IndexOf("end of over", StringComparison.OrdinalIgnoreCase) > 0)
                {
                    words = fileLines[i].Substring(0, fileLines[i].IndexOf("end of over", StringComparison.OrdinalIgnoreCase)).Split(' ', '\t');                    
                }
                else
                {
                    words = fileLines[i].Split(' ', '\t');
                }

                for (int word_index = 1; word_index < words.Length && word_index < 10; word_index++ )
                {
                    if (string.IsNullOrEmpty(words[word_index]))
                    {
                        continue;
                    }

                    if (string.Compare(words[word_index], "four", StringComparison.InvariantCultureIgnoreCase) == 0 || string.Compare(words[word_index], "six", StringComparison.InvariantCultureIgnoreCase) == 0 || string.CompareOrdinal(words[word_index], "4") == 0 || string.CompareOrdinal(words[word_index], "6") == 0)
                    {
                        var presentLineOver = Convert.ToDouble(words[0]);
                        var nextLineOver = Convert.ToDouble(fileLines[i + 1].Substring(0, fileLines[i + 1].IndexOf(' ')));
                        if (nextLineOver - presentLineOver < 0.2)
                        {
                            if (lineAdded == i)
                            {
                                relatedLineNumbers.Add(i + 1);
                                lineAdded = i + 1;
                            }
                            else
                            {
                                relatedLineNumbers.Add(i);
                                relatedLineNumbers.Add(i + 1);
                                lineAdded = i + 1;
                            }
                        }
                        break;
                    }
                }

            }

            var relatedDirectory = Path.Combine(Path.GetDirectoryName(fileName), "RelatedDeliveries");
            if(!Directory.Exists(relatedDirectory))
            {
                Directory.CreateDirectory(relatedDirectory);
            }

            StreamWriter sw = new StreamWriter(Path.Combine(relatedDirectory, Path.GetFileNameWithoutExtension(fileName) + "_related.txt"));

            foreach (var lineNumber in relatedLineNumbers)
            {
                if (fileLines[lineNumber].IndexOf("end of over", StringComparison.OrdinalIgnoreCase) > 0)
                {
                    sw.WriteLine(fileLines[lineNumber].Substring(0, fileLines[lineNumber].IndexOf("end of over", StringComparison.OrdinalIgnoreCase)));
                }
                else
                {
                    sw.WriteLine(fileLines[lineNumber]);
                }
            }
            sw.Close();
        }

        public static void FormatRelationalInstances(string fileName)
        {
            try
            {
                var fileLines = File.ReadAllLines(fileName);
                var numLines = fileLines.Length;
                for (int i = 0; i < numLines - 1; i++)
                {
                    if (string.Compare(fileLines[i], "Boundary No Info", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        i++;
                        if (fileLines[i].IndexOf("Boundary") >= 0)
                        {
                            i--;
                        }
                        continue;
                    }
                    else if (string.Compare(fileLines[i + 1], "Boundary No Info", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        continue;
                    }
                    else if (string.Compare(fileLines[i + 1], "No Info", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        i++;
                        continue;
                    }
                    var line1 = fileLines[i].Substring("Boundary".Length + 1);
                    var line2 = fileLines[i + 1];
                    if (fileLines[i + 1].IndexOf("Boundary") == 0)
                    {
                        line2 = fileLines[i + 1].Substring("Boundary".Length + 1);
                    }
                    string outputFile = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + "_final.txt");
                    File.AppendAllText(outputFile, line1 + "\n" + line2 + "\n");
                    if (fileLines[i + 1].IndexOf("Boundary") != 0)
                    {
                        i++;
                    }
                }
            }
            catch (FileNotFoundException e)
            {
                Trace.WriteLine("Data insufficient for bowling feature relational Dependency. Okay, not an error!");
            }
        }

        public void ReportTransitionMatrix(BowlingFeatures bowlingFeature, string fileName)
        {
            var ballType = new BallType(bowlingFeature);
            var transitionMatrix = AllocateMatrix(ballType.bowlingFeatureDefinition.Count);
            var featureDictionary = GetFeatureDictionary(ballType);

            try
            {
                var fileLines = File.ReadAllLines(fileName);
                var numLines = fileLines.Length;
                for (int i = 0; i < numLines - 1; i++)
                {
                    int rowIndex = featureDictionary[fileLines[i]];
                    int colIndex = featureDictionary[fileLines[i + 1]];
                    transitionMatrix[rowIndex][colIndex]++;
                }

                string outFile = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + "_stats.txt");
                StreamWriter sw = new StreamWriter(outFile);
                for (int i = 0; i < ballType.bowlingFeatureDefinition.Count; i++)
                {
                    sw.Write(ballType.bowlingFeatureDefinition[i] + "\t");
                }
                sw.WriteLine("\n");

                for (int i = 0; i < ballType.bowlingFeatureDefinition.Count; i++)
                {
                    for (int j = 0; j < ballType.bowlingFeatureDefinition.Count; j++)
                    {
                        sw.Write(transitionMatrix[i][j] + "\t");
                    }
                    sw.WriteLine();
                }

                for (int i = 0; i < ballType.bowlingFeatureDefinition.Count; i++)
                {
                    float sum = 0;
                    for (int j = 0; j < ballType.bowlingFeatureDefinition.Count; j++)
                    {
                        sum += transitionMatrix[i][j];
                    }
                    float percentChange = (sum - transitionMatrix[i][i]) * 100 / sum;
                    sw.WriteLine("For " + bowlingFeature + " Type = " + ballType.bowlingFeatureDefinition[i] + " percent change = " + percentChange + "%");
                }

                sw.Close();
            }
            catch (FileNotFoundException e)
            {
                e.GetType();
                Trace.WriteLine("File does not exist, means data not available for transition data for a bowling feature");
            }
        }

        private IDictionary<string, int> GetFeatureDictionary(BallType ballType)
        {
            IDictionary<string, int> featureDictionary = new Dictionary<string, int>();
            for (int i = 0; i < ballType.bowlingFeatureDefinition.Count; i++)
            {
                featureDictionary[ballType.bowlingFeatureDefinition[i]] = i;
            }

            return featureDictionary;
        }

        public int[][] AllocateMatrix(int n)
        {
            int[][] matrix = new int[n][];
            for (int i = 0; i < n; i++)
            {
                matrix[i] = new int[n];
            }
            return matrix;
        }
    }
}
